﻿using AngleSharp;
using AngleSharp.Dom;
using AngleSharp.Html.Dom;
using AngleSharp.Html.Parser;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using mshtml;
using System.Xml.Linq;
using System.Security.Policy;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;

namespace app9_spider
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            webBrowser.Navigate($"http://www.zgcjm.org/achievementList");
            this.KeyPreview = true;
            this.KeyDown += txtURL_KeyDown;
            this.ActiveControl = txtURL;
        }

        private void txtURL_KeyDown(object sender, KeyEventArgs e)
        {
            btn_go_Click(sender, e);
            
        }

        private void Navigate(String address)
        {
            if (String.IsNullOrEmpty(address)) return;
            if (address.Equals("about:blank")) return;
            if (!address.StartsWith("http://") &&
                !address.StartsWith("https://"))
            {
                address = "http://" + address;
            }
            try
            {
                webBrowser.Invoke(new Action(() =>
                {
                    webBrowser.Navigate(new Uri(address));

                    //html = webBrowser.Document.Body.OuterHtml;
                }));// 在子线程中修改控件
                //webBrowser.Navigate(new Uri(address));
            }
            catch (System.UriFormatException)
            {
                return;
            }
        }


        // Updates the URL in TextBoxAddress upon navigation.
        private void webBrowser_Navigated(object sender,
            WebBrowserNavigatedEventArgs e)
        {
            txtURL.Text = webBrowser.Url.ToString();
            Console.WriteLine($">>>>>>>>>>{e.Url.ToString()}");
        }

        private void btn_go_Click(object sender, EventArgs e)
        {
            try
            {
                Navigate(txtURL.Text);
            }
            catch (System.UriFormatException)
            {
                return;
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            if (webBrowser.CanGoBack)
            {
                webBrowser.GoBack();
            }
        }

        private void btnForward_Click(object sender, EventArgs e)
        {
            if (webBrowser.CanGoForward)
            {
                webBrowser.GoForward();
            }
        }

        private void webBrowser1_StatusTextChanged(object sender, EventArgs e)
        {
            this.toolStripStatusLabel1.Text = this.webBrowser.StatusText;
            if (webBrowser.CanGoBack)
            {
                btnBack.Enabled = true;
            }
            else
            {
                btnBack.Enabled=false;
            }
            if (webBrowser.CanGoForward)
            {
                btnForward.Enabled = true;
            }
            else { btnForward.Enabled=false; }
        }


        /// <summary>
        /// 加载完成后事件
        /// </summary>
        /// <returns></returns>
        private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (e.Url == webBrowser.Document.Url)
            {
                // 当前文档完成加载
                ProcessNavigation(); // 继续导航到下一个URL
            }
        }


        private void writeCSV(string FileNamePath, string ID, string name, string intro)
        {
            string data = string.Empty;
            if (File.Exists(FileNamePath))
            {
                FileStream fileStream = new FileStream(FileNamePath, FileMode.Append, FileAccess.Write); //实例化文件流类，并指定为创建模式和写
                StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.UTF8); //实例化流写类，WriteLine()将以UTF8的编码方式写入数据
                data = ID + "," + name + "," + intro ; 
                //把字符串格式的数据用","连接起来以便写入CSV时按逗号分隔
                streamWriter.WriteLine(data); //写入数据
                streamWriter.Close(); //先关闭流写，写完一定要记得关闭，否则文件会被程序打开占用
                fileStream.Close(); //再关闭文件流写，写完一定要记得关闭，否则文件会被程序打开占用
                Console.WriteLine($"{ID},{name},{intro}\n已经写入");
            }
        }

        private static string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //桌面路径
        private static string FileNamePath = $"{desktop}/spider.csv"; //文件路径

        /// <summary>
        /// 检查ID是否已经存在与CSV文件中
        /// </summary>
        /// <param name="csvFilePath"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static bool CheckIfIdExistsInCsv(string csvFilePath, string id)
        {
            bool idExists = false;
            try
            {
                // 确保文件存在
                if (File.Exists(csvFilePath))
                {
                    // 读取文件所有行
                    string[] lines = File.ReadAllLines(csvFilePath);
                    // 假设第一行是标题行，获取其中的ID列索引
                    //int idColumnIndex = Array.IndexOf(lines[0].Split(','), "ID");
                    // 遍历除第一行外的其他行
                    foreach (var line in lines)
                    {
                        // 分割当前行，获取ID列的值
                        string currentId = line.Split(',')[0].Trim('"');
                        // 如果找到匹配的ID，设置标志变量并退出循环
                        if (currentId == id)
                        {
                            idExists = true;
                            break;
                        }
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
            }

            return idExists;
        }


        private int startPage = 0;
        private int endPage = 0;
        private int currentPage = 0;
        private string targetURL = string.Empty;
        private Queue<string> navigationQueue = new Queue<string>();

        private void EnqueueNavigation(string url)
        {
            navigationQueue.Enqueue(url);
            ProcessNavigation();
        }

        private void ProcessNavigation()
        {
            if (navigationQueue.Count > 0)
            {
                string url = navigationQueue.Dequeue();
                webBrowser.Navigate(url);
                webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
                doWork();
            }
        }


        //参考@"https://blog.csdn.net/CGS_______/article/details/105269779"
        private void Delay(int Millisecond)
        {
            DateTime current = DateTime.Now;
            while (current.AddMilliseconds(Millisecond) > DateTime.Now)
            {
                Application.DoEvents();
            }
            return;
        }

        private void doWork()
        {
            while (webBrowser.ReadyState != WebBrowserReadyState.Complete)//&& webBrowser.Url.ToString()!=targetURL
            {
                Application.DoEvents();
            }
            Delay(200);
            string dochtml = webBrowser.Document.Body.OuterHtml;
            var parser = new HtmlParser();
            var dom = parser.ParseDocument(dochtml);
            for (int i = 0;i<3;i++)
            {
                var name = dom.QuerySelector("#info > div.achTitle > div > h1 > i");
                var ID = dom.QuerySelector("#info > div.achTitle > div > ul > li:nth-child(1) > i");
                var intro = dom.QuerySelector("#ty1 > p");
                if (name!=null && ID!=null && intro!=null)
                {
                    string strID = ID.TextContent.Trim();
                    string strName = name.TextContent.Trim();
                    string strIntro = intro.TextContent.Trim();
                    if (!File.Exists(FileNamePath))
                    {
                        File.Create(FileNamePath).Close();
                    }

                    if (!CheckIfIdExistsInCsv(FileNamePath, strID))
                    {
                        writeCSV(FileNamePath, strID, strName, strIntro);
                    }
                    else
                        Console.WriteLine($"ID:{strID}  记录已存在！");
                    return;
                }
                else
                {
                    Console.WriteLine($"第{i + 1}次尝试失败！！！");
                }
            }
        }


        private void btnCtrl_Click(object sender, EventArgs e)
        {
            startPage = int.Parse(txtStart.Text);
            endPage = int.Parse(txtEnd.Text);
            currentPage = startPage;
            progressBar1.Minimum = 0;
            progressBar1.Maximum = endPage-startPage + 1;

            for (int i = 1;  i <= progressBar1.Maximum; i++)
            {
                progressBar1.Value = i;
                label2.Text = $"{i}/{progressBar1.Maximum}";

                targetURL = $"http://www.zgcjm.org/achievementInfo?id={currentPage}";
                EnqueueNavigation(targetURL);
                Console.WriteLine("--------------------------");
                currentPage++;

            }
        }

        private void webBrowser_NewWindow(object sender, CancelEventArgs e)
        {
            webBrowser.Url = new Uri(((WebBrowser)sender).StatusText);
            e.Cancel = true;
        }
    }
}
